package cn.gailvlun.gll.presentation.chat;

import android.app.Activity;
import android.app.Dialog;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.SimpleItemAnimator;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.KeyboardUtils;
import com.github.markzhai.recyclerview.BindingViewHolder;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import cn.gailvlun.gll.R;
import cn.gailvlun.gll.chatkit.dialog.DialogListAdapter;
import cn.gailvlun.gll.chatkit.message.MessageInput;
import cn.gailvlun.gll.chatkit.message.MessageListAdapter;
import cn.gailvlun.gll.chatkit.message.OnClickEmojiListener;
import cn.gailvlun.gll.chatkit.message.OnClickStickerListener;
import cn.gailvlun.gll.chatkit.message.OnVoiceSuccessListener;
import cn.gailvlun.gll.chatlib.ChatClient2;
import cn.gailvlun.gll.chatlib.event.MatchSuccessEvent;
import cn.gailvlun.gll.chatlib.event.MessageEvent;
import cn.gailvlun.gll.chatlib.event.MessageSuccessEvent;
import cn.gailvlun.gll.chatlib.event.RoomCloseEvent;
import cn.gailvlun.gll.chatlib.event.RoomNameEvent;
import cn.gailvlun.gll.chatlib.message.Message;
import cn.gailvlun.gll.chatlib.message.MessageStatus;
import cn.gailvlun.gll.chatlib.message.MessageType;
import cn.gailvlun.gll.databinding.ActivityChatBinding;
import cn.gailvlun.gll.db.DbListRes;
import cn.gailvlun.gll.mgr.UploadMgr;
import cn.gailvlun.gll.mgr.UploadResult;
import cn.gailvlun.gll.net.HttpMethods;
import cn.gailvlun.gll.net.HttpSubscriber;
import cn.gailvlun.gll.net.Member;
import cn.gailvlun.gll.net.apartment.room.ApartmentTask;
import cn.gailvlun.gll.net.apartment.room.GetRoomDetailRes;
import cn.gailvlun.gll.net.apartment.room.RoomStatus;
import cn.gailvlun.gll.net.base.Profile;
import cn.gailvlun.gll.presentation.apartment.ApartmentDetailActivity;
import cn.gailvlun.gll.presentation.apartment.room.IPromiseActivity;
import cn.gailvlun.gll.presentation.apartment.room.dialog.MatchSuccessDialog;
import cn.gailvlun.gll.presentation.apartment.task.TodayTaskActivity;
import cn.gailvlun.gll.presentation.base.BaseActivity;
import cn.gailvlun.gll.presentation.chat.vm.ChatViewModel;
import cn.gailvlun.gll.presentation.profile.OtherProfileActivity;
import cn.gailvlun.gll.util.ClipboardUtil;
import cn.gailvlun.gll.util.DialogUtil;
import cn.gailvlun.gll.util.ImageUtil;
import cn.gailvlun.gll.util.IsEmpty;
import cn.gailvlun.gll.util.LogUtil;
import cn.gailvlun.gll.util.ProfileUtil;
import cn.gailvlun.gll.util.RxUtil;
import cn.gailvlun.gll.util.SPUtil;
import cn.gailvlun.gll.util.StringUtil;
import cn.gailvlun.gll.util.ToastUtil;
import cn.gailvlun.gll.widget.CheckInDialog;
import cn.gailvlun.gll.widget.NavigationBarView;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.realm.RealmResults;
import rx_activity_result2.Result;


public class ChatActivity extends BaseActivity implements OnRefreshListener {

    public static void openActivity(Context context, String dialogId) {
        Intent intent = new Intent(context, ChatActivity.class);
        intent.putExtra("dialogId", dialogId);
        context.startActivity(intent);
    }

    public static void openActivity(Context context, String dialogId, boolean isRefresh) {
        Intent intent = new Intent(context, ChatActivity.class);
        intent.putExtra("dialogId", dialogId);
        intent.putExtra("isRefresh", isRefresh);
        context.startActivity(intent);
    }

    private ActivityChatBinding mBinding;
    private MessageListAdapter mAdapter;
    private LinearLayoutManager mLayoutManager;

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        setIntent(intent);

        if (intent.getBooleanExtra("isRefresh", true)) {
            loadCurrentInfo();
        }
    }

    private ChatViewModel mViewModel;
    private List<Integer> atWhomList;
    private boolean atAll;

    @Override
    protected void initComponent() {
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
        mBinding.setPresenter(new Presenter());

        mBinding.recyclerView.getItemAnimator().setChangeDuration(0);
        ((SimpleItemAnimator) mBinding.recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

        mAdapter = new MessageListAdapter(mContext);
        mBinding.recyclerView.setAdapter(mAdapter);

        mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, true);
//        mLayoutManager.setStackFromEnd(true);
        mBinding.recyclerView.setLayoutManager(mLayoutManager);

        mAdapter.setLayoutManager(mLayoutManager);

        mBinding.mi.setRecordView(mBinding.recordView);


        mBinding.refreshLayout.setEnableRefresh(false);

        mBinding.refreshLayout.setEnableLoadmore(false);

        mBinding.refreshLayout.setEnableOverScrollBounce(false);
        mBinding.refreshLayout.setEnableOverScrollDrag(false);
        mBinding.refreshLayout.setOnRefreshListener(this);
    }

    @Override
    protected void createHandler() {
        mBinding.nbv.setOnBackListener(new NavigationBarView.OnBackListener() {
            @Override
            public void onBack(NavigationBarView nb) {
                onBackPressed();
            }
        });
        mBinding.nbv.setOnMenuClickListener(new NavigationBarView.OnMenuClickListener() {
            @Override
            public void onMenuClick(NavigationBarView nb) {
                if (mViewModel.isGroup()) {
                    GroupSettingActivity.Companion.openActivity(mContext, mViewModel.getChatId())
                            .subscribe(new Consumer<Result<Activity>>() {
                                @Override
                                public void accept(Result<Activity> activityResult) throws Exception {
                                    if (activityResult.resultCode() == RESULT_OK) {
                                        mBinding.nbv.setTitleText(activityResult.data().getStringExtra("roomName"));
                                    }
                                }
                            });
                } else if (mViewModel.isRoom()) {
                    RoomDetailActivity.openActivity(mContext, mViewModel.getChatId())
                            .subscribe(new Consumer<Result<Activity>>() {
                                @Override
                                public void accept(Result<Activity> activityResult) throws Exception {
                                    mViewModel.reloadMyMember();
                                }
                            });
                } else {
                    ChatSettingActivity.openActivity(mContext, mViewModel.getChatId())
                            .subscribe(new Consumer<Result<Activity>>() {
                                @Override
                                public void accept(Result<Activity> activityResult) throws Exception {
                                    if (activityResult.resultCode() == RESULT_OK) {
                                        loadHistoryMessages();
                                    }
                                }
                            });
                }
            }
        });

        mBinding.recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, final int bottom, int oldLeft, int oldTop, int oldRight, final int oldBottom) {
                mBinding.recyclerView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (bottom < oldBottom) {
                            mAdapter.scrollToBottom();
                        }
                    }
                }, 50);
            }
        });

        mBinding.mi.setMOnClickEmojiListener(new OnClickEmojiListener() {
            @Override
            public void onClickEmoji(@NotNull EditText editText, @NotNull String emoji) {
                editText.setText(editText.getText().toString() + emoji);
            }
        });

        mBinding.mi.setMOnClickStickerListener(new OnClickStickerListener() {
            @Override
            public void onClickSticker(@NotNull String stickerLocalPath) {
//                LogUtil.d("test", sticker);
                Message stickerMessage = Message.sticker(stickerLocalPath, new Date(), ProfileUtil.getProfile(), mViewModel.getDialogId());

                int[] widthHeight = ImageUtil.getImageWidthHeight(stickerLocalPath);
                stickerMessage.setWidth(widthHeight[0]);
                stickerMessage.setHeight(widthHeight[1]);

                if (mViewModel.isRoom()) {
                    stickerMessage.setRoom(mViewModel.getRoom());
                    if (!mViewModel.isGroup()) {
                        stickerMessage.setNickName(mViewModel.getMyMember().getNickname());
                    }
                }

                if (ChatClient2.getInstance().sendMessage(stickerMessage)) {
                    mAdapter.addLatest(stickerMessage, true);
                    mViewModel.saveMessage(stickerMessage);
                }
            }
        });

        mBinding.mi.setOnSubmitListener(new MessageInput.OnSubmitListener() {
            @Override
            public void onSubmit(EditText etInput) {
                if (!IsEmpty.string(etInput.getText().toString())) {


                    if (StringUtil.isAllSpace(etInput.getText().toString())) {
                        ToastUtil.showShort("不能发送空白消息");
                        etInput.setText(null);
                        return;
                    }


                    final Message msg;
                    if (mViewModel.isRoom() && !IsEmpty.list(atWhomList) && !atAll) {
                        msg = Message.atWhomText(etInput.getText().toString(), new Date(),
                                ProfileUtil.getProfile(), mViewModel.getDialogId(), false, atWhomList);

                    } else if (mViewModel.isRoom() && atAll) {
                        msg = Message.atWhomText(etInput.getText().toString(), new Date(),
                                ProfileUtil.getProfile(), mViewModel.getDialogId(), true, atWhomList);
                    } else {
                        msg = Message.text(etInput.getText().toString(), new Date(),
                                ProfileUtil.getProfile(), mViewModel.getDialogId());
                    }
                    if (mViewModel.isRoom()) {
                        msg.setRoom(mViewModel.getRoom());
                        if (!mViewModel.isGroup()) {
                            msg.setNickName(mViewModel.getMyMember().getNickname());
                        }
                    }

                    // 消息上屏,呈现 FAIL 状态
                    ChatClient2.getInstance().sendMessage(msg);
                    msg.setMessageStatus(MessageStatus.FAIL_SPINNER);
                    mAdapter.addLatest(msg, true);
                    etInput.setText(null);

                    // 存入数据库
                    mViewModel.saveMessage(msg);

                    // 设置 5s timer
                    compositeDisposable.add(RxUtil.timer(5, TimeUnit.SECONDS)
                            .subscribe(new Consumer<Long>() {
                                @Override
                                public void accept(Long aLong) throws Exception {
                                    // 根据 ID 查找此 message, if it's success, then nothing would happen
                                    // TODO: 2018/9/21 ghy
                                    boolean isSuccess = mViewModel.isMessageSuccess(msg);
                                    if (!isSuccess) {
                                        msg.setMessageStatus(MessageStatus.FAIL_RESEND);

                                        mViewModel.saveMessage(msg);
                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                    }
                                }
                            })
                    );
                    atWhomList = null;
                    atAll = false;
                }
            }
        });

        mBinding.mi.setOnVoiceSuccessListener(new OnVoiceSuccessListener() {
            @Override
            public void onVoiceSuccess(File voiceFile) {

                if (FileUtils.isFileExists(voiceFile)) {
                    final Message wtMsg = Message.localWalkieTalkie(voiceFile.getAbsolutePath(),
                            new Date(), ProfileUtil.getProfile(), mViewModel.getDialogId());
                    if (mViewModel.isRoom()) {
                        wtMsg.setRoom(mViewModel.getRoom());
                        if (!mViewModel.isGroup()) {
                            wtMsg.setNickName(mViewModel.getMyMember().getNickname());
                        }
                    }
                    wtMsg.setWTPlayed(true);


                    UploadMgr.getInstance().upload(FileUtils.getFileName(voiceFile), voiceFile.getPath(), new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                        @Override
                        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                            wtMsg.setWalkieTalkie(request.getObjectKey());

                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    // 消息上屏,呈现 FAIL 状态
                                    ChatClient2.getInstance().sendMessage(wtMsg);
                                    wtMsg.setMessageStatus(MessageStatus.FAIL_SPINNER);
                                    mAdapter.addLatest(wtMsg, true);

                                    // 存入数据库
                                    mViewModel.saveMessage(wtMsg);

                                    // 设置 5s timer
                                    compositeDisposable.add(RxUtil.timer(5, TimeUnit.SECONDS)
                                            .subscribe(new Consumer<Long>() {
                                                @Override
                                                public void accept(Long aLong) throws Exception {
                                                    // 根据 ID 查找此 message, if it's success, then nothing would happen
                                                    // TODO: 2018/9/21 ghy
                                                    boolean isSuccess = mViewModel.isMessageSuccess(wtMsg);
                                                    if (!isSuccess) {
                                                        wtMsg.setMessageStatus(MessageStatus.FAIL_RESEND);

                                                        mViewModel.saveMessage(wtMsg);
                                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(wtMsg));
                                                    }
                                                }
                                            })
                                    );
                                }
                            });
                        }

                        @Override
                        public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                            ToastUtil.showShort("上传失败");
                        }
                    });
                } else {
                    ToastUtil.showShort("录音出错，无法找到录音文件");
                }
            }
        });

        mBinding.mi.setOnPictureSuccessListener(new MessageInput.OnPictureSuccessListener() {
            @Override
            public void onPictureSuccess(File pictureFile, int width, int height) {
                if (width == 0 || height == 0) {
                    int[] size = ImageUtil.getImageWidthHeight(pictureFile.getPath());
                    width = size[0];
                    height = size[1];
                }


                final Message imgMsg = Message.image(null, new Date(), ProfileUtil.getProfile(), mViewModel.getDialogId());
                imgMsg.setLocalImage(pictureFile.getAbsolutePath());
                imgMsg.setHeight(height);
                imgMsg.setWidth(width);
                if (mViewModel.isRoom()) {
                    imgMsg.setRoom(mViewModel.getRoom());
                    if (!mViewModel.isGroup()) {
                        imgMsg.setNickName(mViewModel.getMyMember().getNickname());
                    }
                }
                imgMsg.setMessageStatus(MessageStatus.UPLOADING);

                mAdapter.addLatest(imgMsg, true);
                mViewModel.saveMessage(imgMsg);


                String objectKey = UUID.randomUUID().toString() + '.' + FileUtils.getFileExtension(pictureFile);


                UploadMgr.getInstance().upload(objectKey, pictureFile.getPath())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new SingleObserver<UploadResult<PutObjectRequest, PutObjectResult>>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onSuccess(UploadResult<PutObjectRequest, PutObjectResult> result) {
                                imgMsg.setImage(result.getRequest().getObjectKey());

                                // 呈现 FAIL 状态
                                ChatClient2.getInstance().sendMessage(imgMsg);
                                mViewModel.modifyStatus(imgMsg, MessageStatus.FAIL_SPINNER);
                                mAdapter.notifyItemChanged(mAdapter.getMessagePosition(imgMsg));

                                // 设置 5s timer
                                compositeDisposable.add(RxUtil.timer(5, TimeUnit.SECONDS)
                                        .subscribe(new Consumer<Long>() {
                                            @Override
                                            public void accept(Long aLong) throws Exception {
                                                // 根据 ID 查找此 message, if it's success, then nothing would happen
                                                // TODO: 2018/9/21 ghy
                                                boolean isSuccess = mViewModel.isMessageSuccess(imgMsg);
                                                if (!isSuccess) {
                                                    imgMsg.setMessageStatus(MessageStatus.FAIL_RESEND);

                                                    mViewModel.saveMessage(imgMsg);
                                                    mAdapter.notifyItemChanged(mAdapter.getMessagePosition(imgMsg));
                                                }
                                            }
                                        })
                                );
                            }

                            @Override
                            public void onError(Throwable e) {
                                mViewModel.modifyStatus(imgMsg, MessageStatus.FAIL_UPLOAD);

                                mAdapter.notifyItemChanged(mAdapter.getMessagePosition(imgMsg));
                            }
                        });
            }
        });

        mBinding.mi.setOnReviewCheckListener(new MessageInput.OnReviewCheckListener() {
            @Override
            public void onReviewCheckClick() {
                ReviewCheckInActivity.openActivity(mContext, mViewModel.getChatId());
            }
        });

        mBinding.mi.setOnAtSignListener(new MessageInput.OnAtSignListener() {
            @Override
            public void onAtSign() {
                if (mViewModel.isRoom() != null && mViewModel.isRoom()) {

                    RoomMemberActivity.openActivity(mContext, mViewModel.getRoom().getId(), mViewModel.getMyMember().isIs_host() ? true : false, new Consumer<Result<BaseActivity>>() {
                        @Override
                        public void accept(Result<BaseActivity> activityResult) throws Exception {
                            if (activityResult.resultCode() == Activity.RESULT_OK) {
                                Intent intent = activityResult.data();
                                int memberId = intent.getIntExtra(RoomMemberActivity.EXTRA_MEMBER_ID, -1);
                                int profileId = intent.getIntExtra(RoomMemberActivity.EXTRA_PROFILE_ID, -1);
                                ArrayList<Integer> profileIds = intent.getIntegerArrayListExtra(RoomMemberActivity.EXTRA_PROFILE_IDs);
                                String memberNickName = intent.getStringExtra(RoomMemberActivity.EXTRA_MEMBER_NICK_NAME);
                                atAll = intent.getBooleanExtra(RoomMemberActivity.EXTRA_AT_ALL, false);
                                if (atAll) {
                                    if (atWhomList == null) {
                                        atWhomList = new ArrayList<>();
                                    }
                                    atWhomList.addAll(profileIds);
                                    mBinding.mi.appendText("所有人");
                                } else {

                                    if (atWhomList == null) {
                                        atWhomList = new ArrayList<>();
                                    }
                                    atWhomList.add(profileId);
                                    mBinding.mi.appendText(memberNickName);
                                }
                            }
                        }
                    });

                }
            }
        });

        mAdapter.setOnMessageClickListener(new MessageListAdapter.OnMessageClickListener() {
            @Override
            public void onMessageClick(View view, Message message, int position) {
                if (message.getType() == MessageType.image) {
                    ActivityOptionsCompat options = ActivityOptionsCompat
                            .makeSceneTransitionAnimation(mContext,
                                    view, getString(R.string.shared_image));
                    PhotoActivity.openActivity(mContext, message.getRealImage(), options.toBundle());
                } else if (message.getType() == MessageType.checkIn) {
                    CheckInDialog checkInDialog = new CheckInDialog(mContext, message);
                    checkInDialog.show();
                } else if (message.getType() == MessageType.invite) {
                    if (message.getRoom() != null) {

                        userCheckOutRoomInvite(message);
                    }
                }
            }
        });

        mAdapter.setOnClickPhotoListener(new MessageListAdapter.OnClickPhotoListener() {
            @Override
            public void onClickPhoto(Profile profile) {

                Profile jsonProfile = mViewModel.getCleanProfile(profile);
                OtherProfileActivity.openActivityByChat(mContext, jsonProfile);
            }
        });

        mAdapter.setOnMessageLongClickListener(new MessageListAdapter.OnMessageLongClickListener() {
            @Override
            public boolean onMessageLongClick(final Message message) {
                if (message.getType() == MessageType.text) {
                    new MaterialDialog.Builder(mContext)
                            .items("复制")
                            .itemsCallback(new MaterialDialog.ListCallback() {
                                @Override
                                public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
                                    if (position == 0) {
                                        ClipboardUtil.copyToClipBoard(mContext, "", message.getText());
                                        ToastUtil.showShort("复制成功");
                                    }
                                }
                            })
                            .show();
                    return true;
                }
                return false;
            }
        });

        mAdapter.setOnResendClickListener(new MessageListAdapter.OnResendClickListener() {
            @Override
            public void onResend(final Message msg, final BindingViewHolder holder) {
                new MaterialDialog.Builder(mContext)
                        .content("重发该条消息？")
                        .positiveText("重发")
                        .negativeText("取消")
                        .onPositive(new MaterialDialog.SingleButtonCallback() {
                            @Override
                            public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                                if (msg.getMessageStatus() == MessageStatus.FAIL_RESEND) {

                                    if (!ChatClient2.getInstance().sendMessage(msg)) {
                                        mViewModel.modifyStatus(msg, MessageStatus.FAIL_SPINNER);

                                        mAdapter.notifyItemChanged(holder.getAdapterPosition());
                                        compositeDisposable.add(RxUtil.timer(10, TimeUnit.SECONDS)
                                                .subscribe(new Consumer<Long>() {
                                                    @Override
                                                    public void accept(Long aLong) throws Exception {
                                                        mViewModel.modifyStatus(msg, MessageStatus.FAIL_RESEND);
                                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                                    }
                                                }));
                                    } else {
                                        mViewModel.modifyStatus(msg, MessageStatus.SUCCESS);
                                        mAdapter.notifyItemChanged(holder.getAdapterPosition());
                                    }
                                } else if (msg.getMessageStatus() == MessageStatus.FAIL_UPLOAD) {

                                    mViewModel.modifyStatus(msg, MessageStatus.UPLOADING);
                                    mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));

                                    String objectKey = UUID.randomUUID().toString() + '.' + FileUtils.getFileExtension(msg.getLocalImage());

                                    UploadMgr.getInstance().upload(objectKey, msg.getLocalImage())
                                            .observeOn(AndroidSchedulers.mainThread())
                                            .subscribe(new SingleObserver<UploadResult<PutObjectRequest, PutObjectResult>>() {
                                                @Override
                                                public void onSubscribe(Disposable d) {

                                                }

                                                @Override
                                                public void onSuccess(UploadResult<PutObjectRequest, PutObjectResult> result) {
                                                    mViewModel.setMessageImage(msg, result.getRequest().getObjectKey());
                                                    if (ChatClient2.getInstance().sendMessage(msg)) {
                                                        mViewModel.setMessageImage(msg, "https://img.xiaogaijun.com/" + msg.getImage());
                                                        mViewModel.modifyStatus(msg, MessageStatus.SUCCESS);

                                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                                    } else {
                                                        mViewModel.setMessageImage(msg, "https://img.xiaogaijun.com/" + msg.getImage());
                                                        mViewModel.modifyStatus(msg, MessageStatus.FAIL_SPINNER);

                                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                                        compositeDisposable.add(RxUtil.timer(10, TimeUnit.SECONDS)
                                                                .subscribe(new Consumer<Long>() {
                                                                    @Override
                                                                    public void accept(Long aLong) throws Exception {
                                                                        mViewModel.modifyStatus(msg, MessageStatus.FAIL_RESEND);

                                                                        mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                                                    }
                                                                }));
                                                    }
                                                }

                                                @Override
                                                public void onError(Throwable e) {
                                                    mViewModel.modifyStatus(msg, MessageStatus.FAIL_UPLOAD);

                                                    mAdapter.notifyItemChanged(mAdapter.getMessagePosition(msg));
                                                }
                                            });
                                }
                            }
                        })
                        .show();
            }
        });

        mBinding.mi.setOnCheckCpListener(new MessageInput.OnCheckCpListener() {
            @Override
            public void onCheckCp() {
                CheckCpActivity.openActivity(mContext, mViewModel.getChatId());
            }
        });
    }

    private void userCheckOutRoomInvite(final Message roomInviteMsg) {
        final Dialog pd = DialogUtil.showIndeterminate(mContext);
        HttpMethods.getRoomService()
                .getRoomDetail(roomInviteMsg.getRoom().getId())
                .compose(RxUtil.<GetRoomDetailRes>applyScheduler())
                .compose(this.<GetRoomDetailRes>bindToLifecycle())
                .subscribe(new HttpSubscriber<GetRoomDetailRes>() {
                    @Override
                    protected void onSuccess(GetRoomDetailRes response) {

                        if (response.getRoom().getStatus() == RoomStatus.OPENING && !response.getMember().isIs_match()) {

                            ToastUtil.showShort("抱歉，已开房，你没有权限查看");
                        } else {
                            ApartmentDetailActivity.openActivity(mContext, roomInviteMsg.getRoom().getId(),
                                    roomInviteMsg.getSender().getId());
                        }
                    }

                    @Override
                    protected void onFailure(String errMsg, @Nullable GetRoomDetailRes response, int code) {
                        DialogUtil.showError(mContext, errMsg);
                    }

                    @Override
                    protected void onFinish() {
                        super.onFinish();
                        pd.dismiss();
                    }
                });
    }

    private String mDialogId;

    @Override
    protected void loadData(@Nullable Bundle savedInstanceState) {
        mViewModel = ViewModelProviders.of(this).get(ChatViewModel.class);

        if (getIntent().getBooleanExtra("isRefresh", true)) {
            loadCurrentInfo();
        }
    }

    private void loadCurrentInfo() {
        mDialogId = getIntent().getStringExtra("dialogId");

        mViewModel.loadInfo(mDialogId);

        if (mViewModel.checkIsChatError()) {
            finish();
        }

        mBinding.nbv.setTitleText(mViewModel.getChatTitle());


        if (mViewModel.isNeedPromise()) {
            IPromiseActivity.openActivity(mContext, mViewModel.getMyMember().getId(), new Consumer<Result<Activity>>() {
                @Override
                public void accept(Result<Activity> activityResult) throws Exception {
                    if (activityResult.resultCode() == RESULT_OK) {

                    } else {
                        finish();
                    }
                }
            });
        }

        loadChatCache();

        loadHistoryMessages();

        loadTask();


        changeMessageInput();
    }

    private Disposable disposable;
    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    private void loadChatCache() {
        String cache = mViewModel.getChatCache();
        if (cache != null) {
            mBinding.mi.restoreCache(cache);
        }
    }


    private void loadTask() {

        if (disposable != null) {
            disposable.dispose();
        }

        if (mViewModel.isRoom() && !mViewModel.isRoomOwner()) {
            disposable = mViewModel.getTaskFlowable()
                    .subscribe(new Consumer<RealmResults<ApartmentTask>>() {
                        @Override
                        public void accept(RealmResults<ApartmentTask> apartmentTasks) throws Exception {
                            if (apartmentTasks.size() != 0) {
                                ApartmentTask lastTask = apartmentTasks.get(apartmentTasks.size() - 1);
                                if (mViewModel.isAnyCheckInRelateToMe(lastTask.getId())) {

                                    mBinding.setTask(null);
                                    return;
                                }

                                mBinding.setTask(lastTask);
                            }
                        }
                    });
        }
    }


    private void changeMessageInput() {
        if (mViewModel.isRoom()) {
            if (mViewModel.isRoomOwnerOrLittleOwner()) {
                mBinding.mi.setType(MessageInput.Type.HOST);
            } else {
                mBinding.mi.setType(MessageInput.Type.MEMBER);
            }
        } else {
            mBinding.mi.setType(MessageInput.Type.MEMBER);
        }
    }

    private void loadHistoryMessages() {
        mAdapter.clear();
        DbListRes<Message> dbListRes = mViewModel.getLatestMessages();

        if (!IsEmpty.list(dbListRes.getData())) {

            mAdapter.addDescendingMessages(dbListRes.getData());
            mBinding.refreshLayout.setEnableRefresh(dbListRes.isMore());
            RxUtil.timer(100, TimeUnit.MILLISECONDS)
                    .subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            mAdapter.scrollToBottom();
                        }
                    });
        }
    }

    @Override
    public void onRefresh(RefreshLayout refreshlayout) {

        Message oldestMessage = mAdapter.getOldestMessage();
        DbListRes<Message> dbListRes = mViewModel.getOrderMessage(oldestMessage);
        if (!IsEmpty.list(dbListRes.getData())) {
            mAdapter.addDescendingMessages(dbListRes.getData());
        }
        mBinding.refreshLayout.setEnableRefresh(dbListRes.isMore());
        mBinding.refreshLayout.finishRefresh(0);
    }

    @Override
    public void onBackPressed() {
        mViewModel.saveCache(mBinding.mi.getCache());

        super.onBackPressed();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onNewMessage(MessageEvent event) {
        if (event.dialogId.equals(mViewModel.getDialogId())) {
            Message msg = mViewModel.getMessageById(event.messageId);
            LogUtil.d("received a message: id: " + msg.getId() + ", type: " + msg.getType());
            mAdapter.addLatest(msg, true);

            if (mViewModel.isCheckInMsgRelate2Me(msg) && mBinding.getTask().getId() == msg.getTaskRecord().getTask()) {
                mBinding.llTask.setVisibility(View.GONE);
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMsgSuccess(MessageSuccessEvent event) {
        if (event.dialogId.equals(mViewModel.getDialogId())) {
            // 刷新 UI
            mAdapter.changeMessageToSuccess(event.messageId);
//            Message msg = mViewModel.getMessageById(event.messageId);

        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRoomClose(RoomCloseEvent event) {
        if (mViewModel.isRoom() && event.id == mViewModel.getChatId()) {
            finish();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSkillMatched(MatchSuccessEvent event) {
        if (mViewModel.isSkillRoom(event.roomId)) {
            Member cpMember = mViewModel.getCoupleMember(event.cpMemberId);
            MatchSuccessDialog matchSuccessDialog = new MatchSuccessDialog(mContext, cpMember);
            matchSuccessDialog.setOnMatchListener(new MatchSuccessDialog.OnMatchListener() {
                @Override
                public void onStayInRoom(MatchSuccessDialog dialog) {
                }

                @Override
                public void iKnow(MatchSuccessDialog dialog) {
                    dialog.dismiss();
                }
            });
            matchSuccessDialog.show();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRoomName(RoomNameEvent event) {
        mBinding.nbv.setTitleText(event.roomName);
    }

    @Override
    protected void onDestroy() {

        mAdapter.unbindService();
        SPUtil.put(SPUtil.USER, DialogListAdapter.Util.PRE_HAS_EXIT_AT_MESSAGE, false);

        compositeDisposable.clear();

        if (disposable != null) {
            disposable.dispose();
            disposable = null;
        }

        super.onDestroy();
    }

    public class Presenter {

        public void onClickNewTask(ApartmentTask task) {
            TodayTaskActivity.openActivity(mContext, task);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View v = getCurrentFocus();
            if (isShouldHideKeyboard(ev)) {
                if (KeyboardUtils.isSoftInputVisible(mContext)) {
                    KeyboardUtils.hideSoftInput(mContext);
                } else {
                    mBinding.mi.hideMore();
                }
            } else {
                if (mViewModel.isRoom() && mViewModel.isBlocked()) {
                    ToastUtil.showCenter("你已被禁言，需联系房主解除");
                    return true;
                }
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    private boolean isShouldHideKeyboard(MotionEvent ev) {
        int[] l = {0, 0};
        mBinding.mi.getLocationInWindow(l);
        int top = l[1];
        float y = ev.getY();
        boolean isShould = y < top;
        return isShould;
    }

    public static class Util {
        public static int getTaskVisibility(ApartmentTask item) {
            if (item == null) {
                return View.GONE;
            } else {
                return View.VISIBLE;
            }
        }
    }
}
